/*
 * CS_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND.cpp
 *
 *  Created on: 2014. 1. 8.
 *      Author: jjaehuny
 */


#include "../../Command.h"

#include "../../User.h"
#include "../../NLogic/Space.h"
#include "../../NLogic/Static.h"
#include "../../NResource/Static.h"
#include "../../NLogic/SocialInfo.h"
#include "../../NLogic/Equip.h"
#include "../../NLogic/Stamina.h"

#include "../../Proxy.h"
#include "Common.h"

namespace ProjectZ { namespace NCommand {

static void SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(User * pUser, int16_t ack)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	* pAck << static_cast<int16_t>(ack);
	pAck->MakePacket(CMD_SC_REQ_WORLD_BOSS_CREATE_SINGLE);
	pUser->Send(pAck);
}

void Command::CS_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(User * pUser, ::Network::Packet * pPacket)
{
	/*
	/// 친구와 플레이
	CS_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND	0x400F
	{
		u8 count
		{
			u32	u32gid;			/// 초대할 유저의 gid
		}
	}

	SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND	0x4010
	{
		s16	ack;				/// 1:완료 ,  -1 실패
		u32	party_seq;			/// 파티 시퀀스
	}

	SC_WORLD_BOSS_PARTY_INVITE              0x4018
	{
	   u8 u8party_member_num;           /// min 1 , max 2 본인 제외
	   u16 u16dungeon_tid;
	   u16 u16boss_tid1;
	   u32      party_seq;

	   u16      costume_head;              // 코스튬정보(머리)
	   u16      costume_body;              // 코스튬정보(갑옷)
	   u16 costume_1st_weapon;           // 코스튬정보(무기)
	   u16      costume_2nd_weapon;    // 코스튬정보(보조무기)
	   u16      costume_effect;             // 코스튬정보(이펙트)
	   u16      level;                                     // 레벨
	   u8        class;

	   u32 u32gid;                                                                       /// 방장 GID
	   str struser_id;                                                          /// 카카오톡 사용자 아이디(GUID)  login ID 17자리
	   str struser_nickname;                                      /// 카카오톡 사용자 닉네임.
	   str struser_profile_image_url;                  /// 카카오톡 프로필 이미지 URL
	}


	*/

	NLogic::Space * pWorld = pUser->GetSpace();
	if (NULL == pWorld)
	{
		DEBUGLOG("%s NULL == pWorld", __FUNCTION__);
		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_NO_SPACE);
		return;
	}

	if (false == pUser->EndBattle_afterEffect())
	{
		DEBUGLOG("%s false == pUser->EndBattle_afterEffect()", __FUNCTION__);
		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_BATTLE_AFTEREFFECT);
		return;
	}

	if (pWorld->GetData()._spaceType != NLogic::Space::SpaceType::WORLD)
	{
		DEBUGLOG("%s pWorld->GetData()._spaceType != NLogic::Space::SpaceType::WORLD", __FUNCTION__);
		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_NO_SPACE);
		return;
	}

	if (pUser->GetEnumState() != User::EnumState::__NONE__)
	{
		DEBUGLOG("%s pUser->GetEnumState() != User::EnumState::__NONE__", __FUNCTION__);
		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	NLogic::Equip * pEquip = pUser->GetEquip();
	if (NULL == pEquip)
	{
		DEBUGLOG("%s NULL == pEquip", __FUNCTION__);
		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	NResource::EventTimeResource * pEventTimeResource = NResource::Static::Instance().GetEventTime();
	if (NULL == pEventTimeResource)
	{
		DEBUGLOG("%s NULL == pEventTimeResource", __FUNCTION__);
		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	if (false == pEventTimeResource->IsWorldBossEvent(pUser))
	{
		DEBUGLOG("%s false == pEventTimeResource->IsWorldBossEvent(pUser)", __FUNCTION__);
		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_WORDBOSS_NOT_EVENT);
		return;
	}

	NLogic::Stamina * pStamina = pUser->GetStamina();
	if (NULL == pStamina)
	{
		DEBUGLOG("%s NULL == pStamina", __FUNCTION__);
		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	if (true == pStamina->IsKeyLack(1))
	{
		DEBUGLOG("%s staminaGap < 0", __FUNCTION__);
		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_NOT_ENOUGHT_STAMINA);
		return;
	}

/*	time_t currentSec;
	time(&currentSec);

	// 현재 스태미너가 최대라면 남은 회복 시간을 현재시간으로 설정
	if (pUser->GetCharacterInfo().event_stamina == STAMINA_MAX)
		pUser->GetCharacterInfo().recover_stamina_sec = currentSec;

	int staminaGap = pUser->GetCharacterInfo().event_stamina - 1;

	// 보유 스태미너가 부족한 경우
	if (staminaGap < 0)
	{
		DEBUGLOG("%s staminaGap < 0", __FUNCTION__);
		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_NOT_ENOUGHT_STAMINA);
		return;
	}*/

	NResource::WorldBoss * pWorldBossResource = NResource::Static::Instance().GetWorldBossResource();
	if (NULL == pWorldBossResource)
	{
		DEBUGLOG("%s NULL == pWorldBossResource", __FUNCTION__);
		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	NLogic::Space * pWorldBossSpace = NLogic::Static::Instance().GETSPACEPOOL()->NEW();
	if (NULL == pWorldBossSpace)
	{
		DEBUGLOG("%s NULL == pNewPartyRoomSpace", __FUNCTION__);
		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_UNKNOWN_ERROR);
		return;
	}



	NLogic::Party * pParty = NLogic::Static::Instance().GETPARTYPOOL()->NEW();
	if (NULL == pParty)
	{
		DEBUGLOG("%s NULL == pParty", __FUNCTION__);

		NLogic::Static::Instance().GETSPACEPOOL()->DEL(pWorldBossSpace);

		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_UNKNOWN_ERROR);
		return;
	}


	PREPARE_PACKET;

	char count = 0;

	* pPacket >> count;

	if (count >= 3 || count <= 0)
	{
		DEBUGLOG("%s count > 4 || count <= 0 count : %d", __FUNCTION__, static_cast<int>(count));
		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_UNKNOWN_ERROR);

		NLogic::Static::Instance().GETSPACEPOOL()->DEL(pWorldBossSpace);
		NLogic::Static::Instance().GETPARTYPOOL()->DEL(pParty);

		return;
	}

	std::vector<User *> clsUserVector;

	for (int i = 0; i < count; ++i)
	{
		int userSeq = 0;
		* pPacket >> userSeq;

		auto itr = NProxy::GetUserTree().find(userSeq);
		if (itr == NProxy::GetUserTree().end())
			continue;

		User * pTarget = itr->second;
		if (NULL == pTarget)
			continue;

		NLogic::Space * pSpaceTemp = pTarget->GetSpace();
		if (NULL == pSpaceTemp)
		{
			continue;
		}

		if (pTarget->GetEnumState() != User::EnumState::__NONE__)
			continue;

		NLogic::SocialInfo * pSocialInfo = pTarget->GetSocialInfo();
		if (NULL == pSocialInfo)
			continue;

		NLogic::SocialInfo::Data * pData = pSocialInfo->GetData();
		if (NULL == pData)
			continue;

		if (0 == (pData->_invite_blocked & static_cast<int>(NLogic::SocialInfo::EnumInviteState::DUNGEON_ON)))
			continue;

		clsUserVector.push_back(pTarget);
	}

	if (clsUserVector.size() <= 0)
	{
		::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
		* pAck << static_cast<int16_t>(ACK_DUNGEON_CREATE_PARTY_FRIEND_FAIL);
		* pAck << static_cast<int32_t>(0);
		pAck->MakePacket(CMD_SC_REQ_DUNGEON_CREATE_PARTY_FRIEND);
		pUser->Send(pAck);

		NLogic::Static::Instance().GETSPACEPOOL()->DEL(pWorldBossSpace);
		NLogic::Static::Instance().GETPARTYPOOL()->DEL(pParty);

		return;
	}

	pParty->Open(pUser);

	pWorld->LeaveUser(pUser);

	NLogic::Space::Data clsData;
	clsData._maxUser = clsUserVector.size();
	clsData._table_id = pWorldBossResource->GetData().u16map_id;
	clsData._difficulty = 0;
	clsData._spaceType = NLogic::Space::SpaceType::WORLDBOSS_PARTY_FRIENDS;
	clsData._boss_tid = pWorldBossResource->GetData().u16boss_tid1;

	pWorldBossSpace->Open(pUser, clsData);
	pWorldBossSpace->SetIndexerWorldBoss(NULL);
	pWorldBossSpace->SetParty(pParty);


	NLogic::Static::WORLDBOSSROOMTREE & worldBossRoomTree = NLogic::Static::Instance().GETWORLDBOSSROOMTREE_FRIEND();
	auto itr = worldBossRoomTree.find(pWorldBossSpace->GetData()._index);
	if (itr != worldBossRoomTree.end())
	{
		DEBUGLOG("%s itr != worldBossRoomTree.end() index : %d", __FUNCTION__, pWorldBossSpace->GetData()._index);

		NLogic::Static::Instance().GETSPACEPOOL()->DEL(pWorldBossSpace);
		NLogic::Static::Instance().GETPARTYPOOL()->DEL(pParty);

		SendAck_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	worldBossRoomTree[pWorldBossSpace->GetData()._index] = pWorldBossSpace;

	pWorldBossSpace->EnterUser(pUser);

	pParty->AddInviteUserTree(pUser);
	pUser->SetEnumState(User::EnumState::ACCEPT_WAIT);

	{
		::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
		* pAck << static_cast<int16_t>(ACK_OK);
		* pAck << static_cast<uint32_t>(0);
		pAck->MakePacket(CMD_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND);
		pUser->Send(pAck);
		STRESSLOG("CMD_SC_REQ_WORLD_BOSS_CREATE_PARTY_FRIEND ACK");
	}

	SendWorldBossDetailInfo(pUser);

	std::for_each(clsUserVector.begin(), clsUserVector.end(), [&](User * pLocalUser) {
		pLocalUser->SetEnumState(User::EnumState::INVITE);
		pParty->EnterUser(pLocalUser);
		pParty->AddInviteUserTree(pLocalUser);
	} );

	auto partyAllUserTree = pParty->GetAllUserTree();
	{
		::Network::Packet * pNoti = ::Network::GETPACKETPOOL()->SEND_NEW();
		* pNoti << static_cast<uint8_t>(count);
		* pNoti << static_cast<uint16_t>(pWorldBossResource->GetData().u16dungeon_tid);
		* pNoti << static_cast<uint16_t>(pWorldBossResource->GetData().u16boss_tid1);
		* pNoti << static_cast<uint32_t>(pWorldBossSpace->GetData()._index);

		if (pUser->GetCharacterInfo().avartar_iconidx == 1000)
		{
			* pNoti << static_cast<uint16_t>(pEquip->GetEquipItemIconIndex(ITEM_EQUIP_POS_HELMET));
			* pNoti << static_cast<uint16_t>(pEquip->GetEquipItemIconIndex(ITEM_EQUIP_POS_ARMOR));
			* pNoti << static_cast<uint16_t>(pEquip->GetEquipItemIconIndex(ITEM_EQUIP_POS_WEAPON));
			* pNoti << static_cast<uint16_t>(pEquip->GetEquipItemIconIndex(ITEM_EQUIP_POS_WEAPON));
		}
		else
		{
			* pNoti << static_cast<uint16_t>(pUser->GetCharacterInfo().avartar_iconidx + 100);
			* pNoti << static_cast<uint16_t>(pUser->GetCharacterInfo().avartar_iconidx + 100);
			* pNoti << static_cast<uint16_t>(pUser->GetCharacterInfo().avartar_iconidx + 100);
			* pNoti << static_cast<uint16_t>(pUser->GetCharacterInfo().avartar_iconidx + 100);
		}

		* pNoti << static_cast<uint16_t>(0);
		* pNoti << static_cast<uint16_t>(pUser->GetCharacterInfo().level);
		* pNoti << static_cast<uint8_t>(pUser->GetCharacterInfo().classtype);

		* pNoti << static_cast<uint32_t>(pUser->GetUserSeq());

		* pNoti << pUser->GetSocialID().c_str();
		if( 1 == pUser->GetSocialInfo()->GetData()->_profile_opened )
			* pNoti << pUser->GetUserInfo().nickname.c_str();
		else
			* pNoti << static_cast<uint16_t>(0);

		* pNoti << pUser->GetUserInfo().profile_url.c_str();
		pNoti->MakePacket(CMD_SC_WORLD_BOSS_PARTY_INVITE);

		std::for_each(partyAllUserTree.begin(), partyAllUserTree.end(), [&](NLogic::Party::USERTREE::value_type & pair) {
			User * pReceiver = pair.second;
			if ( pReceiver != pUser)
			{
				pReceiver->SendOneshotEncrypt(pNoti);
			}
		} );

		::Network::GETPACKETPOOL()->SEND_DEL(pNoti);
	}

	pParty->SetState(NLogic::Party::State::WORLD_BOSS_WAIT_FRIEND);
}

} /*NCommand*/ } /*ProjectZ*/

